Electron 作為一個桌面應用框架,提供了非常靈活的視窗管理功能,可以讓開發者輕鬆實現多視窗應用。
無論是獨立的子視窗、彈出窗口,還是互相通信的多視窗程式,Electron 都可以透過其豐富的 API 實現。
在這篇文章中,筆者將介紹如何在 Electron 程式中實現多視窗程式,並探討視窗之間的通信和管理技巧,讓讀者可以透過這些技巧實作出多視窗的應用程式。
在桌面程式開發中,多視窗的場景經常出現,例如:
多視窗的架構允許程式以更加靈活的方式運行,提升使用者體驗,尤其在需要展示大量資訊或進行多任務操作時。
在 Electron 中,視窗是由 BrowserWindow 類創建的。
要實現多視窗程式,我們只需創建多個 BrowserWindow 物件,並載入不同的內容。
const { app, BrowserWindow } = require('electron');
let mainWindow, secondaryWindow;
function createMainWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
},
});
mainWindow.loadFile('index.html'); // 載入主視窗的 HTML
}
function createSecondaryWindow() {
secondaryWindow = new BrowserWindow({
width: 600,
height: 400,
parent: mainWindow, // 將此視窗設定為主視窗的子視窗
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
},
});
secondaryWindow.loadFile('secondary.html'); // 載入子視窗的 HTML
}
app.whenReady().then(() => {
createMainWindow();
createSecondaryWindow();
mainWindow.on('closed', () => {
mainWindow = null;
});
secondaryWindow.on('closed', () => {
secondaryWindow = null;
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
在這個範例中,我們創建了兩個視窗:
mainWindow 是主程式視窗,而 secondaryWindow 是子視窗。每個視窗都可以載入不同的 HTML 文件,顯示不同的內容。
當有多個視窗時,視窗之間的通信就變得至關重要。
Electron 提供了兩種主要的通信方式:
IPC 是最常用的通信方式,特別是在不同的視窗需要與主程序通信時。
以下是一個簡單的範例,展示如何讓子視窗向主視窗發送訊息,並接收主視窗的回覆:
import { ipcMain } from 'electron'
ipcMain.on('message-from-secondary', (event, message) => {
console.log('收到來自子視窗的訊息:', message);
});
import { ipcRenderer } from 'electron'
// 向主程序發送訊息
ipcRenderer.send('message-from-secondary', '你好,這是子視窗');
在這個例子中,子視窗可以向主程序發送訊息,並可以繼續執行後面想要進行的行為,例如調整視窗大小。
如果想要讓不同的視窗之間直接通信,可以使用 Electron 提供的 webContents API。
每個視窗都有自己的 webContents 物件,可以通過它來向其他視窗發送訊息。
// 主視窗接收訊息
mainWindow.webContents.on('message', (event, message) => {
console.log('收到子視窗的訊息:', message);
});
// 子視窗發送訊息息給主視窗
secondaryWindow.webContents.send('message', '來自子視窗的訊息');
這種方式允許你在不通過主程序的情況下,讓多個視窗直接進行通信。
以下呈現兩種方法的混合用法
import { ipcMain } from 'electron'
ipcMain.on('message-from-secondary', (event, message) => {
console.log('收到來自子視窗的訊息:', message);
// 可以向所有視窗廣播訊息
mainWindow.webContents.send('message-from-main', '這是來自主視窗的回覆');
});
import { ipcRenderer } from 'electron'
// 向主程序發送訊息
ipcRenderer.send('message-from-secondary', '你好,這是子視窗');
// 接收來自主視窗的訊息
ipcRenderer.on('message-from-main', (event, message) => {
console.log('收到主視窗的訊息:', message);
});
在這個例子中,子視窗可以向主程序發送訊息,主程序可以接收到訊息並向主視窗和其他視窗回覆。
在多視窗應用中,如何管理視窗的打開、關閉以及生命周期是非常重要的。以下是一些視窗管理的最佳實踐:
在某些應用場景下,子視窗應該與主視窗保持關聯。
當主視窗被關閉時,子視窗應該自動關閉,這可以通過 parent 屬性來設置父子視窗關係。
let childWindow = new BrowserWindow({
parent: mainWindow, // 設置為主視窗的子視窗
modal: true, // 設置為 modal,會鎖住主視窗
show: false // 可以在載入完成後再顯示
});
當設置了 modal 時,子視窗將作為 modal,使用者無法與主視窗互動,直到子視窗被關閉。
視窗的打開與關閉應該是靈活的,並且要根據需求動態管理視窗狀態。
以下是一些打開和關閉視窗的方式:
let secondaryWindow = null;
function createSecondaryWindow() {
if (!secondaryWindow) {
secondaryWindow = new BrowserWindow({
width: 600,
height: 400,
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
},
});
secondaryWindow.loadFile('secondary.html'); // 載入子視窗內容
secondaryWindow.on('close', () => {
secondaryWindow = null; // 清除引用,允許垃圾回收
});
}
}
在某些情況下,你可能需要強制銷毀一個視窗,例如在應用退出時或不再需要子視窗時。
if (secondaryWindow) {
secondaryWindow.destroy(); // 強制銷毀視窗
secondaryWindow = null;
}
function closeSecondaryWindow(window) {
if (secondaryWindow && !secondaryWindow.isDestroyed()) {
secondaryWindow.close(); // 關閉視窗
}
}
在某些情況下,你可能不需要關閉視窗,而是將其隱藏起來,稍後再顯示。
這在某些持續性的應用場景(如工具窗口)中特別有用。
隱藏視窗
secondaryWindow.hide(); // 隱藏視窗
顯示視窗
secondaryWindow.show(); // 顯示已隱藏的視窗
這些方法允許你靈活地控制視窗的打開與關閉,或是顯示及隱藏,並且在需要時釋放資源。
在 Electron 中實現多視窗程式不僅可以擴展程式的功能,還能提升用戶的操作體驗。
通過創建多個 BrowserWindow 視窗、使用 IPC 或 webContents 進行視窗間的通信,你可以構建出功能豐富且靈活的桌面程式。
視窗管理在多視窗應用中扮演了關鍵角色,應用中需要根據具體場景控制視窗的打開、關閉和生命周期。藉助 Electron 的強大 API,你可以輕鬆地實現各種視窗需求,打造多任務、跨螢幕操作的桌面程式(後面的章節會有更多的實例喔,可持續關注~)。
下一篇,我們會將上一篇文章:React 與 Electron 的整合:打造動態的用戶界面 所提到的 桌面計時器 增加多視窗的功能,來示範這篇文章所提到的內容~